<?php
/**
 * Memcached class
 * 
 * @author  jiaowei <jiaowei@178.com>
 * @version $Id: Mem.php 2497 2009-12-25 02:34:20Z jiaowei $
 */

class Mem
{
	/**
	 * 缓存生存期
	 *
	 * @var int
	 */
	protected $_leftTime = 1800;
	
	/**
	 * 是否压缩存储
	 *
	 * @var int
	 */
	protected $_compressed = 0;
	
	/**
	 * memcached object
	 *
	 * @var object
	 */
	protected $_memcache = null;
		
	/**
	 * Singleton
	 *
	 * @var object
	 */
	protected static $_instance;
	
	public static $get_times = 0;
	public static $get_success_times = 0;
	public static $set_times = 0;
	
	/**
	 * 构造函数
	 *
	 */
	public function __construct($config = array())
	{
		//控制将key映射到server的散列函数 crc32
		ini_set('memcache.hash_function', 'crc32');
		
		//控制将key映射到server的策略 consistent 
		ini_set('memcache.hash_strategy', 'consistent');
	
		$this->_memcache = new Memcache;
		
		//memcache config
		if (empty($config)) {
			$config = $_SERVER['config']['memcache'];
		}
		
		foreach ($config AS $v) {
			$this->_memcache->addServer($v['host'], $v['port']);
		}
	}
	
	/**
	 * Singleton Pattern
	 *
	 * @return object
	 */
	public static function getInstance($config = array())
	{
		if ( !(self::$_instance instanceof self) ) {
			self::$_instance = new self($config);
		}
		
		return self::$_instance;
	}
	
	/**
	 * 获取缓存数据
	 * 
	 * string Memcache::get ( string $key )
	 * array  Memcache::get ( array  $keys )
	 * 
	 * @param  mixed $key
	 * @return mixed
	 */
	public function get($key)
	{
		self::$get_times++;
		$ret = $this->_memcache->get($key);
		if ($ret) {
			self::$get_success_times++;
		}
		return $ret;
	}
	
	/**
	 * 存储数据如果该数据没有被缓存
	 * 
	 * 如果成功则返回 TRUE，失败则返回 FALSE。 该函数多用于检测是否key已存在,如果key已存在返回FALSE
	 *
	 * @param  str $key
	 * @param  mixed $data
	 * @param  int $leftTime
	 * @param  int $flag
	 * @return bool
	 */
	public function add($key, $data, $leftTime = false, $flag = 0)
	{
		self::$set_times++;
        if (false === $leftTime) {
			$leftTime = $this->_leftTime;
		}
		
		$flag = $flag ? 'MEMCACHE_COMPRESSED' : 0;
		
        return $this->_memcache->add($key, $data, $flag, $leftTime);
	}
	
	/**
	 * 设置数据缓存
	 * 
	 * 如果成功则返回 TRUE，失败则返回 FALSE。  如果已经存在，则覆写
	 *
	 * @param  str $key
	 * @param  mixed $data
	 * @param  int $leftTime 缓存时间设置为0 将缓存30天
	 * @param  int $flag		是否压缩缓存 默认不压缩
	 * @return bool
	 */
	public function set($key, $data, $leftTime = false, $flag = 0)
	{
		self::$set_times++;
		if (false === $leftTime) {
			$leftTime = $this->_leftTime;
		}
		
		$flag = $flag ? 'MEMCACHE_COMPRESSED' : 0;

        return $this->_memcache->set($key, $data, $flag, $leftTime);
	}
	
	/**
	 * 删除缓存数据
	 *
	 * @param  str $key
	 * @return bool
	 */
	public function remove($key)
	{
		return $this->_memcache->delete($key);
	}
	
	/**
	 * 对一个已有的key进行覆写操作
	 * 
	 * 如果成功则返回 TRUE，失败则返回 FALSE。 如果要替换的key不存在返回FALSE
	 *
	 * @param  str $key
	 * @param  mixed $data
	 * @param  int $leftTime
	 * @param  int $flag
	 * @return bool
	 */
	public function replace($key, $data, $leftTime = false, $flag = 0)
	{
		if (false === $leftTime) {
			$leftTime = $this->_leftTime;
		}
		
        $flag = $flag ? 'MEMCACHE_COMPRESSED' : 0;
        
        return $this->_memcache->replace($key, $data, $flag, $leftTime);
	}
	
	/**
	 * 对保存的某个key中的值进行加法操作
	 * 
	 * 该方法为原子操作
	 *
	 * @param  str $key
	 * @param  int $value
	 * @return bool
	 */
	public function incr($key, $value = 1)
	{
		return $this->_memcache->increment($key, $value);
	}
	
	/**
	 * 对保存的某个key中的值进行减法操作
	 * 
	 * 该方法为原子操作
	 *
	 * @param str $key
	 * @param int $value
	 * @return bool
	 */
	public function decr($key, $value = 1)
	{
		return $this->_memcache->decrement($key, $value);
	}
	
	/**
	 * 清除所有缓存的数据
	 *
	 * @return bool
	 */
	public function clean()
	{
		return $this->_memcache->flush();
	}
	
	/**
	 * 析构函数
	 *
	 */
	public function __destruct()
	{
		
	}
	
	
	/**
     +----------------------------------------------------------
     * 兼容方法
     +----------------------------------------------------------
     */
	public function load($key)
	{
		$tmp = $this->get($key);
        if (is_array($tmp)) {
            return unserialize($tmp[0]);;
        }
		return false;
	}
	
	public function save($value, $key, $tag = array(), $leftTime = false)
	{
		$value = serialize($value);
		return $this->set($key, array($value, time()), $leftTime);
	}
}
